import random
from copy import deepcopy
from TSP import TSP
import matplotlib.pyplot as plt


def ZX(matrix, city_x, city_y, parent1, parent2):
    alpha = random.uniform(0.1, 0.3)
    Lx, Ly = (max(city_x) - min(city_x)) * alpha, (max(city_y) - min(city_y)) * alpha
    choice = random.randint(0, len(parent1) - 1)
    midx, midy = city_x[choice], city_y[choice]
    # midx, midy = (max(city_x) + min(city_x))/2, (max(city_y) + min(city_y))/2
    flag = []
    for position in range(len(parent1)):
        if abs(city_x[position] - midx) < Lx / 2 and abs(city_y[position] - midy) < Ly / 2:
            flag.append(True)
        else:
            flag.append(False)
    print(flag)
    offspring1, offspring2, child = deepcopy([parent1]), deepcopy([parent2]), [[], []]
    for position in range(len(parent1) - 1):
        if flag[parent1[position]] ^ flag[parent1[position + 1]]:
            offspring1.append(parent1[position + 1:])
            for i in range(len(offspring1[-1])):
                offspring1[-2].remove(offspring1[-1][i])
    if len(offspring1) > 1:
        if flag[parent1[-1]] ^ flag[parent1[0]] == 0:
            offspring1[-1] = offspring1[-1] + offspring1[0]
            offspring1 = offspring1[1:]
    for position in range(len(parent1) - 1):
        if flag[parent2[position]] ^ flag[parent2[position + 1]]:
            offspring2.append(parent2[position + 1:])
            for i in range(len(offspring2[-1])):
                offspring2[-2].remove(offspring2[-1][i])
    if len(offspring2) > 1:
        if flag[parent2[-1]] ^ flag[parent2[0]] == 0:
            offspring2[-1] = offspring2[-1] + offspring2[0]
            offspring2 = offspring2[1:]
    print('offspring1', offspring1)
    print('offspring2', offspring2)
    for i in range(len(offspring1)):
        if flag[offspring1[i][0]]:
            child[0].append(offspring1[i])
        else:
            child[1].append(offspring1[i])
    for i in range(len(offspring2)):
        if flag[offspring2[i][0]]:
            child[1].append(offspring2[i])
        else:
            child[0].append(offspring2[i])
    print('child1', child[0])
    print('child2', child[1])
    for num in range(2):
        while len(child[num]) > 1:
            target, flag = 1, False
            for i in range(1, len(child[num])):
                if matrix[child[num][i][0] + 1][child[num][0][-1] + 1] < matrix[child[num][target][0] + 1][
                    child[num][0][-1] + 1]:
                    target = i
            for i in range(1, len(child[num])):
                if not flag:
                    if matrix[child[num][i][-1] + 1][child[num][0][-1] + 1] < matrix[child[num][target][0] + 1][
                        child[num][0][-1] + 1]:
                        target = i
                else:
                    if matrix[child[num][i][-1] + 1][child[num][0][-1] + 1] < matrix[child[num][target][-1] + 1][
                        child[num][0][-1] + 1]:
                        target = i
            if flag:
                child[num][0] = child[num][0] + reversed(child[num][target])
            else:
                child[num][0] = child[num][0] + child[num][target]
            child[num].remove(child[num][target])
        child[num] = child[num][0]
    return child[0], child[1], midx, midy, alpha


case = 'burma14'
tsp_data = TSP(path=f'../../data/TSPLIB/{case}.tsp.txt')
genelength = tsp_data.n
city_x, city_y = tsp_data.x[1:], tsp_data.y[1:]
Distance = tsp_data.distance_matrix
parent = [list(range(genelength)), list(range(genelength))]
for num in range(2):
    random.shuffle(parent[num])
    print(parent[num])
child1, child2, midx, midy, alpha = ZX(Distance, city_x, city_y, parent[0], parent[1])
Lx, Ly = (max(city_x) - min(city_x)) * alpha, (max(city_y) - min(city_y)) * alpha
child = [child1, child2]
for num in range(2):
    print(child[num])

start_point = (midx - Lx / 2, midy - Ly / 2)
fig = plt.figure()
for position in range(len(parent[0])):
    for num in range(2):
        parent[num][position] += 1
        child[num][position] += 1
for num in range(2):
    plt.subplot(2, 2, num + 1)
    plt.gca().add_patch(plt.Rectangle(start_point, Lx, Ly, color='forestgreen', fill=False))
    parent[num].append(parent[num][0])
    tsp_data.draw(plt, route=parent[num], show_text=True)
    plt.title('parent' + str(num + 1))

for num in range(2):
    plt.subplot(2, 2, num + 3)
    plt.gca().add_patch(plt.Rectangle(start_point, Lx, Ly, color='forestgreen', fill=False))
    child[num].append(child[num][0])
    tsp_data.draw(plt, route=child[num], show_text=True)
    plt.title('child' + str(num + 1))

plt.show()
